package pl.kosmowska.ewelina.client.app.activity;

import java.util.Date;

import pl.kosmowska.ewelina.client.Constants;
import pl.kosmowska.ewelina.client.ViewMessages;
import pl.kosmowska.ewelina.client.app.ClientFactory;
import pl.kosmowska.ewelina.client.app.activity.places.InvestmentEditPlace;
import pl.kosmowska.ewelina.client.app.activity.places.InvestmentPlace;
import pl.kosmowska.ewelina.client.app.activity.places.SignInPlace;
import pl.kosmowska.ewelina.client.app.requestfactory.InvestmentDataRequest;
import pl.kosmowska.ewelina.client.app.requestfactory.dto.InvestmentDataProxy;
import pl.kosmowska.ewelina.client.app.user.AuthEvent;
import pl.kosmowska.ewelina.client.app.user.AuthEvent.Auth;
import pl.kosmowska.ewelina.client.app.user.AuthEventHandler;
import pl.kosmowska.ewelina.client.views.InvestmentEditView;

import com.google.gwt.activity.shared.AbstractActivity;
import com.google.gwt.event.shared.EventBus;
import com.google.gwt.place.shared.Place;
import com.google.gwt.user.client.ui.AcceptsOneWidget;
import com.google.gwt.visualization.client.AbstractDataTable;
import com.google.gwt.visualization.client.AbstractDataTable.ColumnType;
import com.google.gwt.visualization.client.DataTable;
import com.google.gwt.visualization.client.VisualizationUtils;
import com.google.gwt.visualization.client.visualizations.PieChart;
import com.google.web.bindery.requestfactory.shared.EntityProxyId;
import com.google.web.bindery.requestfactory.shared.Receiver;
import com.google.web.bindery.requestfactory.shared.Request;
import com.google.web.bindery.requestfactory.shared.ServerFailure;

public class InvestmentEditActivity extends AbstractActivity implements InvestmentEditView.Presenter {

	private InvestmentEditView view;

	private ClientFactory clientFactory;

	private InvestmentDataProxy investmentData;

	private EntityProxyId<InvestmentDataProxy> investmentDataId;

	public InvestmentEditActivity(InvestmentEditPlace place, ClientFactory clientFactory) {
		this.investmentData = place.getInvestmentData();
		this.investmentDataId = place.getInvestmentDataId();
		this.clientFactory = clientFactory;
	}

	@Override
	public void start(AcceptsOneWidget containerWidget, EventBus eventBus) {
		view = clientFactory.getInvestmentEditView();
		view.setPresenter(this);
		initAuthorisationForView();
		if (investmentDataId != null) { 
			getInvestmentData();

		} else {
			view.setData(investmentData);
			startView();
		}
		containerWidget.setWidget(view.asWidget());

	}
	
	private void initAuthorisationForView() {
		if (view.isAlreadyInit() == false) {
			clientFactory.getEventBus().addHandler(AuthEvent.TYPE, new AuthEventHandler() {
				public void onAuthEvent(AuthEvent event) {
					Auth e = event.getAuthEvent();
					if (e == Auth.LOGGEDIN) {
						view.reInitView();
					} else if (e == Auth.LOGGEDOUT) {
						goTo(new SignInPlace());
					}
				}
			});
		}
		view.setAlreadyInit(true);
	}
	
	private void startView() {
		if (clientFactory.getIsLoggedIn() == null) {
			// wait for login event b/c hasn't happened yet
		} else if (clientFactory.getIsLoggedIn() == true) {
			view.reInitView();
		} else if (clientFactory.getIsLoggedIn() == false) { 
			goTo(new SignInPlace());
		}	
	}

	private void getInvestmentData() {
		Request<InvestmentDataProxy> request = clientFactory.getRequestFactory().getInvestmentDataRequest().find(investmentDataId);
		request.fire(new Receiver<InvestmentDataProxy>() {
			public void onSuccess(InvestmentDataProxy investmentData) {
				setData(investmentData);
				view.setData(investmentData);
				startView();
			}

			public void onFailure(ServerFailure error) {
				super.onFailure(error);
			}
		});

	}
	private void setData(InvestmentDataProxy investmentData) {
		this.investmentData = investmentData;

	}

	/**
	 * Navigate to a new Place in the browser
	 */
	public void goTo(Place place) {
		clientFactory.getPlaceController().goTo(place);
	}


	@Override
	public void saveInvestmentData(String name, float value, float totalValue, int monthNumber,
			float percentage, int installmentChoice, Date startDate, Date endDate) {
		// get the requestContext
		InvestmentDataRequest investmentRequest = clientFactory.getRequestFactory().getInvestmentDataRequest();

		// is it create or edit
		InvestmentDataProxy data = null;
		if (investmentData == null) { // insert|create
			data = investmentRequest.create(InvestmentDataProxy.class);

		} else { // update|edit
			data = investmentRequest.edit(investmentData);
		}

		// persist these
		data.setName(name);
		data.setTotalValue(totalValue);
		data.setValue(value);
		data.setMonthNumber(monthNumber);
		data.setPercentage(percentage);
		data.setInstallmentChoice(installmentChoice);
		data.setStartDate(startDate);
		data.setEndDate(endDate);		


		investmentRequest.persist(data).fire(new Receiver<InvestmentDataProxy>() {
			public void onSuccess(InvestmentDataProxy InvestmentData) {
				clientFactory.getPlaceController().goTo(new InvestmentPlace());
			}
			public void onFailure(ServerFailure error) {
				view.showMessage(ViewMessages.ERROR_ON_PERSIST);
				super.onFailure(error);
			}
		}); 

	}

	@Override
	public void goToInvestmentPlace() {
		goTo(new InvestmentPlace());
		
	}

	@Override
	public void calculateInvestment(String name, float clientCapital, float percentage,
			Date startDate, int installmentChoice, int monthNumber) {
		int capitalizationPeriod=1;
		int capitalizationPerYear=1;
		float capitalizationPercentage;
		if(installmentChoice==0){
			capitalizationPeriod=1;
			capitalizationPerYear=12;
		}else if(installmentChoice==1){
			capitalizationPeriod=3;
			capitalizationPerYear=4;
		}else if(installmentChoice==2){
			capitalizationPeriod=12;
			capitalizationPerYear=1;
		}
		
		Date endDate = initEndDate(startDate, monthNumber);
		
		capitalizationPercentage=(float) (percentage*0.01/capitalizationPerYear);
		int capitalizationNumber=monthNumber/capitalizationPeriod; 
		float finalCapital=clientCapital;
		float interestsTaxFree;
		float tax=0;
		for(int i=0; i<capitalizationNumber; i++){
			interestsTaxFree=finalCapital*capitalizationPercentage;
			tax+=interestsTaxFree*(Constants.BELKA_TAX);
			interestsTaxFree*=(1-Constants.BELKA_TAX);
			finalCapital+=interestsTaxFree;
		}
		tax = (float) round(tax);
		float investmentCapital=(float) round(finalCapital);
		
		float interestAmount = finalCapital-clientCapital;
		view.showSummary(clientCapital, investmentCapital, interestAmount, tax, endDate);
		loadViewChart(clientCapital,interestAmount);
	}
	
	private void loadViewChart(final float clientCapital, final float interestAmount) {
		Runnable onLoadCallback = new Runnable() {
			public void run() {
				view.loadChart (createTableForSummaryChart(clientCapital,interestAmount ));
			}
		};
		VisualizationUtils.loadVisualizationApi(onLoadCallback, PieChart.PACKAGE);
		
	}

	private AbstractDataTable createTableForSummaryChart(float clientCapital, float interestAmount) {
		DataTable data = DataTable.create();
		data.addColumn(ColumnType.STRING, "Dzial");
		data.addColumn(ColumnType.NUMBER, "Wartość");
		data.addRows(2);
		data.setValue(0, 0, "Kapitał klienta");
		data.setValue(0, 1, round(clientCapital));
		data.setValue(1, 0, "Odsetki");
		data.setValue(1, 1, round(interestAmount));
		return data;
	}
	
    private Date initEndDate(Date startDate, int monthNumber ) {
		int monthSum=startDate.getMonth()+monthNumber;
		int years=(monthSum+1)/12;
		int month=(monthSum)%12;
		Date endDate=new Date(startDate.getTime());
		endDate.setMonth(month);
		endDate.setYear(startDate.getYear()+years);
		return endDate;
	}

	private double round (double val)
    {
        double exp = Math.pow(10, 2);
        double rounded = val * exp;
        rounded = Math.round(rounded);
        return rounded / exp;
    }

}
